/*
  Copyright (c) 2011, Mikheev Rostislav
  Copyright (c) 2011, FreshFarsh team

  Steel Engine source code is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
/**
  @author Mikheev Rostislav <hacenator@gmail.com>
  @date 23.03.2011
  @brief Configurator source file
*/

#include "config.h"

namespace _STEEL_NAMESPACE {

Config * Config::_instance = NULL;

Config * Config::GetInstance() {
  if (_instance == NULL)
    _instance = new Config();

  return _instance;
}

Config::Config() :
  BasicClass()
{
  _variables.set_empty_key(NULL);

  //TODO(hacenator) Don't forget fix this limits
  _max_int = 10;//std::numeric_limits<int>::digits10 + numeric_limits<int>::is_signed + 2;
  _max_float = 15;//std::numeric_limits<float>::digits10 + numeric_limits<float>::is_signed + 5;
}

Config::~Config() {
  // TODO(hacenator): looks like somethink missed here
  Clear();
}

void Config::Clear() {
  for (std::list<const char *>::iterator it = _values.begin(); it != _values.end(); ++it) {
    delete *it;
  }
  _values.clear();
  _variables.clear();
}

/*const char* jConfig::operator[](key_type& key) {
    return _variables[name];
}*/

const char *Config::GetString(const char *key) {
  return _variables[key];
}

int Config::GetInteger(const char *key) {
  return atoi(_variables[key]);
}

float Config::GetFloat(const char *key) {
    return atof(_variables[key]);
}

const char *Config::GetDefaultString(const char *key, const char *default_value) {
  if (_variables.find(key) == _variables.end()) {
    return default_value;
  } else {
    return _variables[key];
  }
}

int Config::GetDefaultInteger(const char *key, int default_value) {
  if (_variables.find(key) == _variables.end()) {
    return default_value;
  } else {
    return atoi(_variables[key]);
  }
}

float Config::GetDefaultFloat(const char * key, float default_value) {
  if (_variables.find(key) == _variables.end()) {
    return default_value;
  } else {
    return atof(_variables[key]);
  }
}

void Config::SetString(const char *key, const char *value) {
  // already exists
  if (_variables.find(key) != _variables.end()) {
    _values.remove(_variables[key]);
    delete _variables[key];
  }

  char * new_value;
  int len = strlen(value);
  new_value = new char[len + 1];
  strcpy(new_value, value);
  _values.push_back(new_value);

  _variables[key] = new_value;
}

void Config::SetInteger(const char *key, int value) {
  char buf[_max_int];

#if DEBUG
  int len = sprintf(buf, "%d", value);
  if (len > _max_int) {
    _console->Errorf("Integer buffer overflow. With length: %d\n", len);
  }
#else
  sprintf(buf, "%d", value);
#endif

  SetString(key, buf);
}

void Config::SetFloat(const char *key, float value) {
  char buf[_max_float];

#if DEBUG
  int len = sprintf(buf, "%.3f", value);
  if (len > _max_float) {
    _console->Errorf("Float buffer overflow. With length: %d\n", len);
  }
#else
  sprintf(buf, "%.3f", value);
#endif
  SetString(key, buf);
}

}
